import os
import uuid
from datetime import datetime

from django.db import transaction
from rest_framework import serializers

from common.models.base_data import ProjectInfo, ProjectInfoUpdateLog, ProjectWarn, GroupCustomerInfo, \
    GroupInformationStatistics, MobileUserRecord, SpecialLineManagement, InformationPlatformRecord, \
    BusinessOpportunityRecord, ArrearsInformationRecord
from common.models.system import Dept, Users
from settings import conf
from utils.models import get_fieds_values  # 这里可能是拼写错误，建议改成 get_fields_values
from utils.serializers import CustomModelSerializer, ImportCharField, ImportDictionaryField


# ========== 基础序列化器（只读） ==========
class ArrearsInformationRecordSerializer(CustomModelSerializer):
    """欠费信息表 - 基础序列化器（用于查询）"""
    # 关联集团信息（显示集团名称，非ID）
    group = serializers.StringRelatedField(
        source='group.group_name',
        read_only=True,
        label='关联集团名称'
    )

    class Meta:
        model = ArrearsInformationRecord
        fields = '__all__'
        read_only_fields = [
            'id', 'create_time', 'update_time',
            'creator_id', 'dept_belong_id', 'is_del'
        ]
        extra_kwargs = {
            'group_id': {'write_only': True}  # 外键ID仅用于写入，不返回给前端
        }


# ========== 创建/更新专用序列化器 ==========
class ArrearsInformationRecordCreateUpdateSerializer(CustomModelSerializer):
    """欠费信息表 - 创建/更新序列化器（含业务逻辑）"""
    # 关联集团外键（允许空，支持通过ID关联）
    group_id = serializers.PrimaryKeyRelatedField(
        queryset=GroupCustomerInfo.objects.all(),
        allow_null=True,
        required=False,
        label='关联集团ID',
        error_messages={
            'does_not_exist': '指定的集团信息不存在'
        }
    )

    class Meta:
        model = ArrearsInformationRecord
        fields = '__all__'
        read_only_fields = ['id', 'create_time', 'update_time']  # 创建时可写其他字段

    def validate(self, attrs):
        """业务规则校验"""
        # 校验账期顺序
        if attrs.get('min_billing_period') > attrs.get('max_billing_period'):
            raise serializers.ValidationError('最小账期不能晚于最大账期')
        # 校验金额非负数
        for field in ['total_arrears', 'stock_arrears', 'new_arrears', 'current_bad_debt']:
            if attrs.get(field, 0) < 0:
                raise serializers.ValidationError(f'{field}不能为负数')
        return attrs

    def create(self, validated_data):
        """创建时自动填充默认值"""
        # 自动计算欠费账期数（可选业务逻辑）
        if not validated_data.get('arrears_period_count'):
            validated_data['arrears_period_count'] = (
                    (validated_data['max_billing_period'] - validated_data['min_billing_period']).days // 30 + 1
            )
        return super().create(validated_data)

    def update(self, instance, validated_data):
        """更新时的特殊处理"""
        # 保留历史账期不可修改（示例）
        if 'min_billing_period' in validated_data or 'max_billing_period' in validated_data:
            raise serializers.ValidationError('已生效的账期范围不可修改')
        return super().update(instance, validated_data)


class InformationPlatformRecordSerializer(CustomModelSerializer):
    class Meta:
        model = InformationPlatformRecord
        fields = '__all__'
        read_only_fields = ['id']


class InformationPlatformRecordCreateUpdateSerializer(CustomModelSerializer):
    class Meta:
        model = InformationPlatformRecord
        fields = '__all__'
        read_only_fields = ['id']

    def create(self, validated_data):
        # 在这里可以添加创建记录时的额外逻辑
        return super().create(validated_data)


class BusinessOpportunityRecordSerializer(CustomModelSerializer):
    class Meta:
        model = BusinessOpportunityRecord
        fields = '__all__'
        read_only_fields = ['id']


class BusinessOpportunityRecordCreateUpdateSerializer(CustomModelSerializer):
    class Meta:
        model = BusinessOpportunityRecord
        fields = '__all__'
        read_only_fields = ['id']

    def create(self, validated_data):
        # 在这里可以添加创建记录时的额外逻辑
        return super().create(validated_data)


class SpecialLineManagementSerializer(CustomModelSerializer):
    class Meta:
        model = SpecialLineManagement
        fields = '__all__'
        read_only_fields = ['id']


class SpecialLineManagementCreateUpdateSerializer(CustomModelSerializer):
    class Meta:
        model = SpecialLineManagement
        fields = '__all__'
        read_only_fields = ['id']

    def create(self, validated_data):
        now_date = datetime.today().date()
        statistics, _ = GroupInformationStatistics.objects.get_or_create(group_id=validated_data['group'].id)
        with transaction.atomic():
            obj = super().create(validated_data)
            # 不是null 并且 >=当前日期，状态正常，需要累加记录数量；到期数据无需累加
            # 数据专线：更新 数据专线条数、数据专线合计月收入、存量数据专线条数（我网、异网合计）
            if obj.data_line_expiry and obj.data_line_expiry >= now_date:
                statistics.data_line_cnt += obj.data_line_count
                statistics.data_line_income += obj.data_line_income
                statistics.stock_data_line_cnt += obj.data_line_count
                obj.data_line_is_exp = False
            # 互联网专线：更新 互联网专线条数、互联网专线合计月收入、存量互联网专线条数（我网、异网合计）
            if obj.internet_line_expiry and obj.internet_line_expiry >= now_date:
                statistics.internet_line_cnt += obj.internet_line_count
                statistics.internet_line_income += obj.internet_line_income
                statistics.stock_internet_line_cnt += obj.internet_line_count
                obj.internet_line_is_exp = False
            # LT专线：更新  LT数据专线条数、LT互联网专线条数、存量数据专线条数、存量互联网专线条数、异网专线合计月收入
            if obj.lt_expiry and obj.lt_expiry >= now_date:
                statistics.lt_data_line_cnt += obj.lt_data_count
                statistics.lt_internet_line_cnt += obj.lt_internet_count
                statistics.other_net_income += obj.lt_data_fee + obj.lt_internet_fee
                statistics.stock_data_line_cnt += obj.lt_data_count
                statistics.stock_internet_line_cnt += obj.lt_internet_count
                obj.lt_is_exp = False
            # DX专线：更新  DX数据专线条数、DX互联网专线条数、存量数据专线条数、存量互联网专线条数、异网专线合计月收入
            if obj.dx_expiry and obj.dx_expiry >= now_date:
                statistics.dx_data_line_cnt += obj.dx_data_count
                statistics.dx_internet_line_cnt += obj.dx_internet_count
                statistics.other_net_income += obj.dx_data_fee + obj.dx_internet_fee
                statistics.stock_data_line_cnt += obj.dx_data_count
                statistics.stock_internet_line_cnt += obj.dx_internet_count
                obj.dx_is_exp = False
            # GD专线：更新  GD数据专线条数、GD互联网专线条数、存量数据专线条数、存量互联网专线条数、异网专线合计月收入
            if obj.gd_expiry and obj.gd_expiry >= now_date:
                statistics.gd_data_line_cnt += obj.gd_data_count
                statistics.gd_internet_line_cnt += obj.gd_internet_count
                statistics.other_net_income += obj.gd_data_fee + obj.gd_internet_fee
                statistics.stock_data_line_cnt += obj.gd_data_count
                statistics.stock_internet_line_cnt += obj.gd_internet_count
                obj.gd_is_exp = False

            obj.save(update_fields=('update_time', 'data_line_is_exp', 'internet_line_is_exp',
                                    'lt_is_exp', 'dx_is_exp', 'gd_is_exp'))
            statistics.save()

        return obj


class MobileUserRecordSerializer(CustomModelSerializer):
    class Meta:
        model = MobileUserRecord
        fields = '__all__'
        read_only_fields = ['id']


class MobileUserRecordCreateUpdateSerializer(CustomModelSerializer):
    class Meta:
        model = MobileUserRecord
        fields = '__all__'
        read_only_fields = ['id']

    def create(self, validated_data):
        now_date = datetime.today().date()
        statistics, _ = GroupInformationStatistics.objects.get_or_create(group_id=validated_data['group'].id)
        with transaction.atomic():
            obj = super().create(validated_data)
            # 不是null 并且 >=当前日期，状态正常，需要累加记录数量；到期数据无需累加
            if obj.group_5g_coin_exp_date and obj.group_5g_coin_exp_date >= now_date:
                statistics.our_net_user_cnt += obj.our_net_users
                statistics.wiring_box_cnt += obj.wiring_box_penetration
                statistics.joint_pay_user_cnt += obj.joint_pay_users
                statistics.group_5g_coin_user_cnt += obj.our_net_5g_coin_users
                obj.group_5g_coin_is_exp = False
            if obj.lt_exp_date and obj.lt_exp_date >= now_date:
                statistics.lt_user_cnt += obj.lt_users
                statistics.lt_contract_gift_user_cnt += obj.lt_contract_gift_users
                obj.lt_is_exp = False
            if obj.dx_exp_date and obj.dx_exp_date >= now_date:
                statistics.dx_user_cnt += obj.dx_users
                statistics.dx_contract_gift_user_cnt += obj.dx_contract_gift_users
                obj.dx_is_exp = False

            obj.save(update_fields=('update_time', 'group_5g_coin_is_exp', 'lt_is_exp', 'dx_is_exp'))
            statistics.save(update_fields=(
                'our_net_user_cnt', 'wiring_box_cnt', 'joint_pay_user_cnt',
                'group_5g_coin_user_cnt', 'lt_user_cnt', 'lt_contract_gift_user_cnt',
                'dx_user_cnt', 'dx_contract_gift_user_cnt', 'update_time'))

        return obj


class GroupInformationStatisticsCreateUpdateSerializer(CustomModelSerializer):
    class Meta:
        model = GroupInformationStatistics
        fields = '__all__'
        read_only_fields = ['id']


class GroupInformationStatisticsSerializer(CustomModelSerializer):
    class Meta:
        model = GroupInformationStatistics
        fields = '__all__'


class GroupCustomerInfoSerializer(CustomModelSerializer):
    statistics = GroupInformationStatisticsSerializer(read_only=True)

    class Meta:
        model = GroupCustomerInfo
        read_only_fields = ['id']
        fields = '__all__'


class GroupCustomerInfoCreateUpdateSerializer(CustomModelSerializer):
    class Meta:
        model = GroupCustomerInfo
        fields = '__all__'
        read_only_fields = ['id']

    def validate(self, validated_data):
        # 这里可以添加自定义的验证逻辑，如果有需要的话
        return validated_data

    def create(self, validated_data):
        # 检查集团名称是否已存在
        old = GroupCustomerInfo.objects.filter(group_name=validated_data['group_name']).first()
        if old:
            raise serializers.ValidationError('该集团名称已存在')

        validated_data['dept_belong_id'] = validated_data['dept'].id
        with transaction.atomic():
            obj = super().create(validated_data)
            GroupInformationStatistics.objects.create(group_id=obj.id)
        return obj

    def update(self, instance, validated_data):
        # 检查除当前实例外，是否有其他记录使用了相同的集团名称
        old = GroupCustomerInfo.objects.filter(
            group_name=validated_data.get('group_name', instance.group_name)).exclude(
            group_id=instance.group_id).first()
        if old:
            raise serializers.ValidationError('该集团名称已存在')
        return super().update(instance, validated_data)


class ProjectSerializer(CustomModelSerializer):
    no_update_day = serializers.SerializerMethodField()

    class Meta:
        model = ProjectInfo
        read_only_fields = ['id']
        fields = '__all__'

    def get_no_update_day(self, obj):
        return (datetime.now() - obj.update_time).days


class ProjectCreateUpdateSerializer(CustomModelSerializer):
    class Meta:
        model = ProjectInfo
        fields = '__all__'
        read_only_fields = ['id']

    def validate(self, validated_data):
        validated_data['dept_belong_id'] = validated_data['dept'].id
        return validated_data

    def create(self, validated_data):
        old = ProjectInfo.objects.filter(name=validated_data['name']).first()
        if old:
            raise serializers.ValidationError('该项目名称已存在')

        return super().create(validated_data)

    def update(self, instance, validated_data):
        old = ProjectInfo.objects.filter(name=validated_data['name']).exclude(id=instance.id).first()
        if old:
            raise serializers.ValidationError('该项目名称已存在')

        before = get_fieds_values(instance)

        with transaction.atomic():
            # 更新数据
            obj = super().update(instance, validated_data)
            # 变更记录
            after = get_fieds_values(obj)
            if before == after:
                raise serializers.ValidationError('无修改内容')
            ProjectInfoUpdateLog.objects.create(
                project_id=instance.id, before=before, after=after, creator_id=self.request.user.id)
            # 消除预警
            ProjectWarn.objects.filter(project_id=obj.id).update(is_handled=True)
        return obj


class ProjectUpdateLogSerializer(CustomModelSerializer):
    creator_name = serializers.SlugRelatedField(
        slug_field='name', source='creator', read_only=True
    )
    update_fields = serializers.SerializerMethodField()

    class Meta:
        model = ProjectInfoUpdateLog
        read_only_fields = ['id']
        fields = '__all__'

    def get_update_fields(self, obj):
        # 找出两个字典中都存在但值不同的键值对
        common_diff = {k: obj.after[k] for k in obj.before if k in obj.after and obj.before[k] != obj.after[k]}
        return common_diff


class ProjectWarnSerializer(CustomModelSerializer):
    project_name = serializers.SlugRelatedField(slug_field='name', source='project', read_only=True)
    project_dept_id = serializers.SlugRelatedField(slug_field='dept_id', source='project', read_only=True)

    class Meta:
        model = ProjectWarn
        read_only_fields = ['id']
        fields = '__all__'


class ImportProjectSerializer(serializers.Serializer):
    dept_id = ImportCharField(help_text='县区')
    name = ImportCharField(help_text='项目名称')
    price = ImportCharField(help_text='商机规模（万元）')
    jf_name = ImportCharField(help_text='单位名称')
    creator_id = ImportCharField(help_text='项目跟进人')
    important_level = ImportDictionaryField('project_level', help_text='项目级别（红、黄、绿）')
    priority_level = ImportDictionaryField('priority_level', help_text='项目类别')

    def validate_name(self, value):
        if ProjectInfo.objects.filter(name=value).exists():
            raise serializers.ValidationError('项目名称已存在')
        return value

    def validate_dept_id(self, value):
        dept = Dept.objects.filter(name=value).first()
        if not dept:
            raise serializers.ValidationError('区县不存在')
        return dept.id

    def validate_creator_id(self, value):
        user = Users.objects.filter(name=value).first()
        if not user:
            raise serializers.ValidationError('项目跟进人不存在')
        return user.id

    def save(self, **kwargs):
        validated_data = self.validated_data
        validated_data['dept_belong_id'] = validated_data['dept_id']
        instance = ProjectInfo.objects.create(**validated_data)
        return instance


class ReportRecordUploadSerializer(serializers.Serializer):
    template_type = None

    # def validate(self, validated_data):
    #     file_path = os.path.join(conf.STATIC_ROOT, validated_data['file_path'])
    #     validated_data['file_path'] = file_path
    #     return validated_data

    def validate(self, validated_data):
        # 导入文件保存到本地
        file = self.initial_data.get('file')
        converted_date = datetime.today().strftime('%Y%m%d')
        file_dir = os.path.join(conf.STATIC_ROOT, 'upload/{}'.format(converted_date))
        if not os.path.exists(file_dir):
            os.makedirs(file_dir)
        file_path = os.path.join(file_dir, '{0}_{1}'.format(uuid.uuid4(), file.name))
        with open(file_path, 'wb+') as destination:
            for chunk in file.chunks():
                destination.write(chunk)
        validated_data['file_name'] = file.name
        validated_data['file_path'] = file_path
        return validated_data
